package com.wl.mvi.web

import android.annotation.SuppressLint
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Bitmap
import android.net.Uri
import android.net.http.SslError
import android.os.Build
import android.text.TextUtils
import android.util.AttributeSet
import android.util.Log
import android.view.View
import android.webkit.JsResult
import android.webkit.SslErrorHandler
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebResourceError
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.core.view.isVisible
import com.wl.lib.dialog.ConfirmDialogBuilder
import com.wl.lib.utils.ApplicationHelper
import com.wl.lib.utils.ResUtils


// Created by wangliang on 2024/12/6
@SuppressLint("SetJavaScriptEnabled")
class CommonWebView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : WebView(context, attrs, defStyleAttr) {
    companion object {
        private const val REQUEST_CODE_SHOW_FILE_CHOOSER = 101
    }

    private var showFileChooserCallback: ValueCallback<Array<Uri>>? = null

    var navigator: Navigator? = null

    init {
        settings.allowFileAccess = true
        settings.allowContentAccess = true
        webChromeClient = object : WebChromeClient() {

            override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
                showDialog(message ?: "", result)
                return true
            }

            override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
                showDialog(message ?: "", result)
                return true
            }

            override fun onShowFileChooser(
                webView: WebView?,
                filePathCallback: ValueCallback<Array<Uri>>?,
                fileChooserParams: FileChooserParams?
            ): Boolean {
                Log.d("WLTest", "onShowFileChooser")
                showFileChooserCallback = filePathCallback
                val intent = Intent(Intent.ACTION_GET_CONTENT)
                intent.setType("*/*")
                intent.addCategory(Intent.CATEGORY_OPENABLE)
                try {
                    navigator?.startActivityForResult(
                        Intent.createChooser(intent, ResUtils.getString(R.string.choose_file)),
                        REQUEST_CODE_SHOW_FILE_CHOOSER
                    )
                } catch (e: ActivityNotFoundException) {
                    showFileChooserCallback?.onReceiveValue(null)
                    showFileChooserCallback = null
                    Toast.makeText(ApplicationHelper.getInstance(), R.string.no_file_chooser, Toast.LENGTH_SHORT).show()
                    return false
                }
                return true
            }
        }

        // 解决自动播放不能通过代码控制, 提示必须通过 user gesture 触发的问题
        settings.mediaPlaybackRequiresUserGesture = false

        settings.domStorageEnabled = true
        settings.javaScriptEnabled = true
        settings.databaseEnabled = true
        settings.loadsImagesAutomatically = true

        settings.domStorageEnabled = true
        settings.blockNetworkImage = false
        settings.mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW

        // 设置此属性，可任意比例缩放
        settings.useWideViewPort = true

        // 适应webview
        settings.loadWithOverviewMode = true
    }

    private fun showDialog(message: String, result: JsResult?) {
        val activity = (parent as View).context as? Activity
        if (activity == null || activity.isFinishing) {
            return
        }
        ConfirmDialogBuilder(activity)
            .setDescription(message)
            .setPositiveAction({ dialogInterface: DialogInterface ->
                dialogInterface.dismiss()
                result?.confirm()
            })
            .setCancelable(true) {
                result?.cancel()
            }
            .buildAndShow()
    }

    fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (requestCode == REQUEST_CODE_SHOW_FILE_CHOOSER) {
            if (showFileChooserCallback != null) {
                val uris = WebChromeClient.FileChooserParams.parseResult(resultCode, data)
                uris?.forEach {

                    Log.d("WLTest", "choose uri: $it")
                }
                showFileChooserCallback?.onReceiveValue(uris)
                showFileChooserCallback = null
            }
        }
    }
}

class CommonWebViewClient(val progressBar: ProgressBar? = null, val titleView: TextView? = null) : WebViewClient() {
    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        return super.shouldOverrideUrlLoading(view, request)
    }

    override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
        super.onPageStarted(view, url, favicon)
        Log.d("WLTest", "onPageStarted url $url")
        progressBar?.isVisible = true
    }

    override fun onPageFinished(view: WebView, url: String) {
        super.onPageFinished(view, url)
        Log.d("WLTest", "onPageFinished url $url")
        progressBar?.isVisible = false
        setTitleFromWebView(view)
    }

    private fun setTitleFromWebView(webView: WebView?) {
        webView ?: return
        webView.post {
            webView.evaluateJavascript(
                "(function() { return window.jsTitle!=undefined ? jsTitle():document.title; })();"
            ) { t: String ->
                //value即为js返回值
                if (!TextUtils.isEmpty(t) && "null" != t && t.length > 2) {
                    val unescaped = t.substring(1, t.length - 1) // remove wrapping quotes
                        .replace("\\\\", "\\") // unescape \\ -> \
                        .replace("\\\"", "\"") // unescape \" -> "
                    titleView?.text = unescaped
                    titleView?.isVisible = true
                }
            }
        }
    }

    @RequiresApi(Build.VERSION_CODES.M)
    override fun onReceivedError(view: WebView, request: WebResourceRequest, error: WebResourceError) {
        super.onReceivedError(view, request, error)
        Log.d("WLTest", "onReceivedError ${error.description}")
        progressBar?.isVisible = false
    }

    override fun onReceivedHttpError(
        view: WebView?,
        request: WebResourceRequest?,
        errorResponse: WebResourceResponse?
    ) {
        super.onReceivedHttpError(view, request, errorResponse)
        Log.d("WLTest", "onReceivedHttpError ${errorResponse?.statusCode}")
        progressBar?.isVisible = false
    }

    @SuppressLint("WebViewClientOnReceivedSslError")
    override fun onReceivedSslError(view: WebView, handler: SslErrorHandler, error: SslError) {
        super.onReceivedSslError(view, handler, error)
    }
}

interface Navigator {
    fun startActivityForResult(intent: Intent, requestCode: Int)
}